<!--
     被动式选择列表，通过输入data属性进行数据的设置，一般用于静态数据的选择
     对于动态查询则使用高级控件selectControl
-->
<template>
    <div :class="classes" v-clickoutside="handleClose">
        <div :class="[prefixCls + '-selection']" ref="reference" @click="toggleMenu">
          <slot name="input">
            <div class="ivu-tag" v-for="(item, index) in selectedMultiple" :key="index">
                <span class="ivu-tag-text">{{ item.label }}</span>
                <Icon type="ios-close-empty" @click.native.stop="removeTag(index)"></Icon>
            </div>
            <span :class="[prefixCls + '-placeholder']" v-show="showPlaceholder && !filterable">{{ localePlaceholder }}</span>
            <span :class="[prefixCls + '-selected-value']" v-show="!showPlaceholder && !multiple && !filterable">
                {{ selectedSingle }}
            </span>
            <input type="text" @keyup.enter="inputEnter" v-if="filterable" :disabled="disabled" v-model="query" :class="[prefixCls + '-input']" :placeholder="showPlaceholder ? localePlaceholder : ''" :style="inputStyle" @blur="handleBlur" @keydown="resetInputState" @keydown.delete="handleInputDelete" @input="filterInput" ref="input">
            <Icon type="ios-close" :class="[prefixCls + '-arrow']" v-show="showCloseIcon" @click.native.stop="clearSingleSelect"></Icon>
            <Icon type="arrow-down-b" :class="[prefixCls + '-arrow']" v-if="!remote"></Icon>
             </slot>
        </div>
        <transition :name="transitionName">
            <Drop :class="dropdownCls" v-show="dropVisible" :placement="placement" ref="dropdown" :data-transfer="transfer" v-transfer-dom>
                <ul v-show="notFountShow" :class="[prefixCls + '-not-found']">
                    <li>{{ localeNotFoundText }}</li>
                </ul>
                <ul v-show="!loading && !notFountShow" :class="[prefixCls + '-dropdown-list']">
                    <slot>
                        <Option v-for="(item,index) in data" v-if="item" :value="getOptionKey(item,index)" :key="getOptionKey(item,index)">
                            <slot :item="item">{{optionText(item,index)}}</slot>
                        </Option>
                    </slot>
                </ul>
                <ul v-show="isRemote && !fetching && (!data||!data.length)" :class="[prefixCls + '-loading']">
                    {{noDataText}}
                </ul>
                <ul v-show="fetching" :class="[prefixCls + '-loading']">
                    <div class="text-spin">
                        <Spin></Spin>
                        <div>{{fetchingText}}</div>
                    </div>
                </ul>
                <ul v-show="loading " :class="[prefixCls + '-loading']">{{ localeLoadingText }}</ul>
            </Drop>
        </transition>
        <input :name="name" v-model="value" type="hidden">
    </div>
</template>

<script>
import { Select } from "iview";
import $ from "@/common";

export default {
  extends: Select,
  props: {
    name: {},
    fetching: {
      default: false
    },
    placeholder: {},
    //输入数据是否为纯字符串
    string: {
      default: false
    },
    filterable: {
      default: false
    },
    optionCode: {
      default: "name"
    },
    renderTpl: {},
    optionKey: {
      default: "id"
    },
    //触发翻页事件的距离
    turnningDistance: {
      type: Number,
      default: 100
    },
    isRemote: {
      default: false
    },
    data: {
      default() {
        return [];
      }
    },
    transfer: {
      default: true
    }
  },
  data() {
    return {
      fetchingText: "数据加载中",
      noDataText: "未查询到数据",
      hasOpen: false
    };
  },
  computed: {
    showPlaceholder() {
      let status = false;
      if (this.data.length === 0) {
        return true;
      }
      if (typeof this.model === "string") {
        if (this.model === "") {
          status = true;
        }
      } else if (Array.isArray(this.model)) {
        if (!this.model.length) {
          status = true;
        }
      } else if (this.model === null || this.model === undefined) {
        status = true;
      }
      return status;
    },
    notFountShow() {
      return false;
    }
  },
  watch: {
    dropVisible(v) {
      if (v) {
        this.$emit("selectOpen");
        this.hasOpen = true;
      } else {
        this.$emit("selectClose");
      }
    },
    data() {
      this.$nextTick(() => {
        this.updateOptions(false, false, true);
      });
    },
    value(val) {
      this.model = val;
      if (val === "" || (val === null && this.data.length === 0)) {
        this.query = "";
      }
    },
    query(val) {
      if (this.remote && this.remoteMethod) {
        if (!this.selectToChangeQuery) {
          this.$emit("on-query-change", val);
          this.remoteMethod(val);
        }
        this.focusIndex = 0;
        this.findChild(child => {
          child.isFocus = false;
        });
      } else {
        if (!this.selectToChangeQuery) {
          this.$emit("on-query-change", val);
        }
        this.broadcastQuery(val);

        let is_hidden = true;

        this.$nextTick(() => {
          this.findChild(child => {
            if (!child.hidden) {
              is_hidden = false;
            }
          });
          this.notFound = is_hidden;
        });
      }
      this.selectToChangeQuery = false;
      this.broadcast("Drop", "on-update-popper");
    }
  },
  methods: {
    debouncedAppendRemove() {
      return debounce(function() {
        if (!this.isRemote) {
          this.modelToQuery();
          this.$nextTick(() => this.broadcastQuery(""));
        } else if (this.remote) {
          this.findChild(child => {
            child.updateSearchLabel(); // #1865
            child.selected = this.multiple
              ? this.model.indexOf(child.value) > -1
              : this.model === child.value;
          });
        }
        this.slotChange();
        this.updateOptions(true);
      });
    },
    //回车自动选中第一条数据
    inputEnter() {
      if (this.dropVisible && this.options && this.options[0]) {
        this.$emit("on-select-selected", this.options[0].value);
      }
    },
    resetScrollTop() {
      const index = this.focusIndex - 1;
      if (!this.optionInstances[index]) return;
      let bottomOverflowDistance =
        this.optionInstances[index].$el.getBoundingClientRect().bottom -
        this.$refs.dropdown.$el.getBoundingClientRect().bottom;
      let topOverflowDistance =
        this.optionInstances[index].$el.getBoundingClientRect().top -
        this.$refs.dropdown.$el.getBoundingClientRect().top;

      if (bottomOverflowDistance > 0) {
        this.$refs.dropdown.$el.scrollTop += bottomOverflowDistance;
      }
      if (topOverflowDistance < 0) {
        this.$refs.dropdown.$el.scrollTop += topOverflowDistance;
      }
    },
    toggleMenu() {
      if (this.disabled) {
        return false;
      }
      this.visible = !this.visible;
    },
    filterInput() {
      if (this.queryTime) {
        clearTimeout(this.queryTime);
      }
      this.queryTime = setTimeout(() => {
        if (!this.hasOpen) return;
        this.$emit("query", this.query);
        this.queryTime = null;
      }, 300);
    },
    hideMenu() {
      this.visible = false;
      this.focusIndex = 0;
      this.broadcast("iOption", "on-select-close");
    },
    dataUpdate() {},
    //添加额外参数 dataUpdate 表示是否为数据变化类型，为true时后续将不会触发select的关闭方法
    updateOptions(init, slot = false, dataUpdate = false) {
      if (this.isRemote) init = false;
      let options = [];
      let index = 1;

      this.findChild(child => {
        options.push({
          value: child.value,
          label: child.label === undefined ? child.$el.innerHTML : child.label
        });
        child.index = index++;
        this.optionInstances.push(child);
      });
      this.options = options;
      if (this.init || !this.hasOpen) {
        this.updateSingleSelected(true, slot, dataUpdate);
        this.updateMultipleSelected(true, slot);
      }
    },
    updateSingleSelected(init = false, slot = false, dataUpdate = false) {
      const type = typeof this.model;
      if (type === "string" || type === "number") {
        let findModel = false;
        for (let i = 0; i < this.options.length; i++) {
          if (this.model === this.options[i].value) {
            this.selectedSingle = this.options[i].label;
            if (!this.hasOpen) {
              this.query = this.selectedSingle;
            }
            findModel = true;
            break;
          }
        }
        //原版条件为slot && !findModel
        if (!findModel) {
          //为范围之外的值提供展示
          this.selectedSingle = this.model;
          //this.model = ''
          this.query = "";
        }
      } else {
        if (this.data.length === 0) {
          //this.query = "";
        }
      }
      this.toggleSingleSelected(this.model, init, dataUpdate);
    },
    toggleSingleSelected(value, init = false, dataUpdate = false) {
      if (!this.multiple) {
        let label = "";

        this.findChild(child => {
          if (child.value === value) {
            child.selected = true;
            label =
              child.label === undefined ? child.$el.innerHTML : child.label;
          } else {
            child.selected = false;
          }
        });

        if (!dataUpdate) {
          this.hideMenu();
        }

        if (!init) {
          if (this.labelInValue) {
            this.$emit("on-change", {
              value: value,
              label: label
            });
            this.dispatch("FormItem", "on-form-change", {
              value: value,
              label: label
            });
          } else {
            this.$emit("on-change", value);
            this.dispatch("FormItem", "on-form-change", value);
          }
        }
      }
    },
    listScroll(e) {
      var el = e.currentTarget;
      //判断滚动条与底部距离是否小于最大值，触发事件
      if (
        el.scrollHeight - el.scrollTop - el.clientHeight <
        this.turnningDistance
      ) {
        this.$emit("turning");
      }
    },
    getOptionKey(v, i) {
      if (this.string) {
        return v;
      } else {
        if (typeof v !== "object") {
          return i;
        } else {
          return v[this.optionKey];
        }
      }
    },
    optionText(v, i) {
      if (this.string) {
        return v;
      }
      if (this.renderTpl) {
        return v._name || $.composeValue(this.renderTpl, v);
      } else {
        if (typeof v !== "object") {
          return v;
        } else {
          return v._name || v[this.optionCode] || v[this.optionKey];
        }
      }
    },
    clearSingleSelect() {
      if (this.showCloseIcon) {
        this.findChild(child => {
          child.selected = false;
        });
        this.model = "";

        if (this.filterable) {
          this.query = "";
        }
      }
    }
  },
  mounted() {
    this.$nextTick(() => {
      this.$refs.dropdown.$el.addEventListener("scroll", e =>
        this.listScroll(e)
      );
    });
  },
  created() {}
};

function debounce(fn) {
  let waiting;
  return function() {
    if (waiting) return;
    waiting = true;
    const context = this,
      args = arguments;
    const later = function() {
      waiting = false;
      fn.apply(context, args);
    };
    this.$nextTick(later);
  };
}
</script>

<style lang="less">
ul.ivu-select-loading {
  font-size: 12px;
}
</style>
